
#pragma once
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <vulkan/vulkan_core.h>
#include "ce_vulkan_struct.h"

class CE_VulkanContext;

class CE_VulkanManager
{
private:
     CE_VulkanManager(/* args */);
     ~CE_VulkanManager();
     CE_VulkanManager(const CE_VulkanManager &) = delete;            // 禁用拷贝构造
     CE_VulkanManager &operator=(const CE_VulkanManager &) = delete; // 禁用赋值操作符

     /**
      * @brief 窗口句柄
      */
     GLFWwindow *_window;
     
     /**
      * @brief Vulkan实例句柄
      */
     VkInstance _vkinstance;
     /**
      * @brief 创建Vulkan实例
      */
     void _createInstance();
     std::vector<const char *> _getRequiredExtensions();
     void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo);
     static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType,
                                                         const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData)
     {
          std::cerr << "Error Message: " << pCallbackData->pMessage << std::endl;
          return VK_FALSE;
     }

     /**
      * @brief Vulkan表面句柄
      */
     VkSurfaceKHR _surface; // 用于显示的窗口句柄
     /**
      * @brief 创建Vulkan表面
      */
     void _createSurface();

     /**
      * @brief 物理设备句柄
      */
     VkPhysicalDevice _physicalDevice;
     /**
      * @brief 初始化物理设备
      */
     void _initPhysicalDevice();
     bool _isDeviceSuitable(VkPhysicalDevice device);
     bool _checkValidationLayerSupport();
     bool _checkDeviceExtensionSupport(VkPhysicalDevice device);

     VkQueue _presentQueue; // 用来存储逻辑设备的图形呈现队列句柄
     VkQueue _graphicsQueue;
     /**
      * @brief 逻辑设备句柄
      */
     VkDevice _vkdevice;
     void _createLogicalDevice();

     CE_VulkanContext *_context;
    
public:
     static CE_VulkanManager *getInstance();
     void init(GLFWwindow *window);

     void addUIObject(std::string id);
     void updateUIObjectShader(std::string id, std::string shaderPath);
     void updateUIObjectVertexs(std::string id,std::vector<float> positions, std::vector<int> indices);
     void updateUIObjectColor(std::string id, float r, float g, float b, float a);

     VkQueue getPresentQueue(); // 用来存储逻辑设备的图形呈现队列句柄
     VkQueue getGraphicsQueue();

     void drawFrame();
     void destroy();

     SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
     std::vector<char> readShaderFile(const std::string &filename);
     VkShaderModule createShaderModule(const std::vector<char> &code);
     QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);
     VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkBuffer *buffer, VkDeviceMemory *memory, VkDeviceSize size, void *data);
     uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties);
};
